/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.ui.rich.full.command;

import java.util.ArrayList;
import java.util.ListIterator;

import javax.swing.JInternalFrame;

import br.ufmg.dees.insane.commons.command.Command;
import br.ufmg.dees.insane.commons.controller.Controller;
import br.ufmg.dees.insane.commons.dialogs.TabbedDialog;
import br.ufmg.dees.insane.commons.view.DrawingArea;
import br.ufmg.dees.insane.crossSection.CrossSection;
import br.ufmg.dees.insane.materialMedia.material.LinearElasticIsotropic;
import br.ufmg.dees.insane.model.disc.analysismodel.AnalysisModel;
import br.ufmg.dees.insane.model.disc.analysismodel.Beam;
import br.ufmg.dees.insane.model.disc.analysismodel.Grid;
import br.ufmg.dees.insane.model.disc.analysismodel.PlaneFrame;
import br.ufmg.dees.insane.model.disc.analysismodel.PlaneTruss;
import br.ufmg.dees.insane.model.disc.element.FrameElement;
import br.ufmg.dees.insane.model.disc.element.force.ElementForce;
import br.ufmg.dees.insane.model.disc.fem.FemModel;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;
import br.ufmg.dees.insane.ui.rich.full.InsaneInternalInterface;
import br.ufmg.dees.insane.ui.rich.full.dialogs.ElmAttributesDialog;

/**
 *
 * @author Fonseca, Flavio & Pitangueira, Roque
 * @since March 2004
 */
public class SetElmAttributesCommand implements Command, Cloneable {
	
	private InsaneInternalInterface parent;
	private Controller controller;
	private DrawingArea da;
	private FemModel fmodel;
	
//*****************************************************************************
	
	/** Creates new SetElmAttributesCommand */
	public SetElmAttributesCommand(JInternalFrame parent) {
		this.parent = (InsaneInternalInterface)parent;
		controller = this.parent.getController();
		da = this.parent.getDrawing();
		fmodel = this.parent.getModel().getDiscreteModel();
	}
	
//*****************************************************************************
	
	/** Execute method. */
	public void execute() {
		
		boolean changed = false;
		
		ArrayList elms = controller.getSelection();
		if ( elms.size() < 1 ) {
			controller.selectAll();
			elms = controller.getSelection();
		}
		
		if (elms.size() == 0) {
			parent.addOutputText("There is no elements in model.");
			return;
		}
		
        ElmAttributesDialog dlg = new ElmAttributesDialog(parent);
        int retVal = dlg.showDialog();
        if (retVal == TabbedDialog.OK_OPTION){
			
			ListIterator elements = elms.listIterator();
			while(elements.hasNext()) {
				FrameElement elm = (FrameElement)elements.next();
				
				//setting elm analysis model
				AnalysisModel anl = null;
				
				if (dlg.anlTypeChosen == null) {
					return;
				} else if (dlg.anlTypeChosen.equals("Beam")) {
					anl = new Beam();
				}
				else if (dlg.anlTypeChosen.equals("Plane Frame")) {
					anl = new PlaneFrame();
				}
				else if (dlg.anlTypeChosen.equals("Plane Truss")) {
					anl = new PlaneTruss();
				}
				else if (dlg.anlTypeChosen.equals("Grid")) {
					anl = new Grid();
				}
				
				boolean existentAnl = false;
				
				ListIterator anls = fmodel.getAnalysisModelsList().listIterator();
				while (anls.hasNext()) {
					AnalysisModel anl2 = (AnalysisModel) anls.next();
					if (anl2.getType().equals(anl.getType()))
						existentAnl = true;
				}
				
				if (elm.getAnalysisModel() == null)
					changed = true;
				else if (elm.getAnalysisModel() != null) {
					if (!elm.getAnalysisModel().getType().equals(anl.getType()))
						changed = true;
				}
				
				if (!existentAnl) {
					fmodel.add(anl);
					elm.setAnalysisModel(anl);
					elm.setShape(fmodel);
				} else {
					elm.setAnalysisModel(fmodel.getAnalysisModel(anl.getType()));
					elm.setShape(fmodel);
				}
				//end of setting elm analysis model
				
				//Setting Material
				if (dlg.modified)
					changed = true;
				if (elm.getMaterial() != null) {
				    LinearElasticIsotropic elmMaterial = (LinearElasticIsotropic)elm.getMaterial();
				    LinearElasticIsotropic newMaterial = (LinearElasticIsotropic)fmodel.getMaterial(dlg.matLabel);
					if (!elmMaterial.getLabel().equals(dlg.matLabel))
						changed = true;
					if (elmMaterial.getMaterialValues(elmMaterial.ELASTICITY).doubleValue() != newMaterial.getMaterialValues(elmMaterial.ELASTICITY).doubleValue())
						changed = true;
					if (elmMaterial.getMaterialValues(elmMaterial.SHEAR_MODULUS).doubleValue() != newMaterial.getMaterialValues(elmMaterial.SHEAR_MODULUS).doubleValue())
						changed = true;
					if (elmMaterial.getMaterialValues(elmMaterial.POISSON).doubleValue() != newMaterial.getMaterialValues(elmMaterial.POISSON).doubleValue())
						changed = true;
					if (elmMaterial.getMaterialValues(elmMaterial.THERMAL_COEFF).doubleValue() != newMaterial.getMaterialValues(elmMaterial.THERMAL_COEFF).doubleValue())
						changed = true;
				} else {
					changed = true;
				}
				elm.setMaterial(fmodel.getMaterial(dlg.matLabel));
				
				//Setting CrossSection
				if (elm.getCrossSection() != null) {
					CrossSection elmSection = elm.getCrossSection();
					CrossSection newSection = fmodel.getCrossSection(dlg.secLabel);
					if (!elmSection.getLabel().equals(dlg.secLabel))
						changed = true;
					if (elmSection.getIx() != newSection.getIx())
						changed = true;
					if (elmSection.getIy() != newSection.getIy())
						changed = true;
					if (elmSection.getIz() != newSection.getIz())
						changed = true;
					if (elmSection.getArea() != newSection.getArea())
						changed = true;
					if (elmSection.getHeight() != newSection.getHeight())
						changed = true;
					if (elmSection.getThickness() != newSection.getThickness())
						changed = true;
				} else {
					changed = true;
				}
				elm.setCrossSection(fmodel.getCrossSection(dlg.secLabel));
				
				//Setting ElmPointForcesList
				if (elm.getElmPointForcesList().size() != dlg.concForces.size()) {
					changed = true;
				} else {
					ListIterator cfs1 = elm.getElmPointForcesList().listIterator();
					ListIterator cfs2 = dlg.concForces.listIterator();
					while (cfs1.hasNext()) {
						PointForce cf1 = (PointForce)cfs1.next();
						PointForce cf2 = (PointForce)cfs2.next();
						if (cf1.getCoord().x != cf2.getCoord().x)
							changed = true;
						if (cf1.getForce(0) != cf2.getForce(0))
							changed = true;
						if (cf1.getForce(1) != cf2.getForce(1))
							changed = true;
						if (cf1.getForce(2) != cf2.getForce(2))
							changed = true;
						if (cf1.getForce(3) != cf2.getForce(3))
							changed = true;
						if (cf1.getForce(4) != cf2.getForce(4))
							changed = true;
						if (cf1.getForce(5) != cf2.getForce(5))
							changed = true;
					}
				}
				
				ArrayList<PointForce> cforces = new ArrayList<PointForce>();
				ListIterator cfs = dlg.concForces.listIterator();
				while (cfs.hasNext()) {
					PointForce cf = (PointForce)cfs.next();
					PointForce cf2 = new PointForce();
					if (cf.getCoord().x > elm.getLength()){
						cf2.getCoord().x = elm.getLength();
					} else {
						cf2.setCoord(cf.getCoord());
					}
					cf2.setForce(0, cf.getForce(0));
					cf2.setForce(1, cf.getForce(1));
					cf2.setForce(2, cf.getForce(2));
					cf2.setForce(3, cf.getForce(3));
					cf2.setForce(4, cf.getForce(4));
					cf2.setForce(5, cf.getForce(5));
					cforces.add(cf2);
				}
				elm.setElmPointForcesList(cforces);
				
				//Setting ElementForcesList
				ArrayList<ElementForce> dforces = new ArrayList<ElementForce>();
				ListIterator dfs = dlg.distForces.listIterator();
				while (dfs.hasNext()) {
					ElementForce ef = (ElementForce)dfs.next();
					PointForce pf1 = (PointForce)ef.getPointForcesList().get(0);
					PointForce pf2 = (PointForce)ef.getPointForcesList().get(1);
					ElementForce ef2 = new ElementForce();
					PointForce pf1a = new PointForce();
					PointForce pf2a = new PointForce();
					
					if (pf1.getCoord().x > elm.getLength()){
						pf1a.getCoord().x = elm.getLength();
					} else {
						pf1a.setCoord(pf1.getCoord().x, 0, 0);
					}
					pf1a.setForce(0, pf1.getForce(0));
					pf1a.setForce(1, pf1.getForce(1));
					pf1a.setForce(2, pf1.getForce(2));
					pf1a.setForce(3, pf1.getForce(3));
					pf1a.setForce(4, pf1.getForce(4));
					pf1a.setForce(5, pf1.getForce(5));
					ef2.getPointForcesList().add(0, pf1a);
					
					if (pf2.getCoord().x > elm.getLength()){
						pf2a.getCoord().x = elm.getLength();
					} else {
						pf2a.setCoord(pf2.getCoord().x, 0, 0);
					}
					pf2a.setForce(0, pf2.getForce(0));
					pf2a.setForce(1, pf2.getForce(1));
					pf2a.setForce(2, pf2.getForce(2));
					pf2a.setForce(3, pf2.getForce(3));
					pf2a.setForce(4, pf2.getForce(4));
					pf2a.setForce(5, pf2.getForce(5));
					ef2.getPointForcesList().add(1, pf2a);
					
					if (pf1a.getCoord().x==0 && pf2a.getCoord().x==0) {
						pf2a.getCoord().x = elm.getLength();
					}
					
					dforces.add(ef2);
				}
				elm.setElmLineForcesList(dforces);
				
				//Setting TemperatureChanges
				if (elm.getDeltaTemp(0) != dlg.Ts)
					changed = true;
				if (elm.getDeltaTemp(1) != dlg.Tn)
					changed = true;
				if (elm.getDeltaTemp(2) != dlg.Ti)
					changed = true;
				elm.setDeltaTemp(0, dlg.Ts);
				elm.setDeltaTemp(1, dlg.Tn);
				elm.setDeltaTemp(2, dlg.Ti);
				
				//Setting InitialEquivalentNodalForce
				if (elm.getInitialNodalForce(0) != dlg.eqFx1)
					changed = true;
				if (elm.getInitialNodalForce(1) != dlg.eqFy1)
					changed = true;
				if (elm.getInitialNodalForce(2) != dlg.eqFz1)
					changed = true;
				if (elm.getInitialNodalForce(3) != dlg.eqMx1)
					changed = true;
				if (elm.getInitialNodalForce(4) != dlg.eqMy1)
					changed = true;
				if (elm.getInitialNodalForce(5) != dlg.eqMz1)
					changed = true;
				if (elm.getInitialNodalForce(6) != dlg.eqFx2)
					changed = true;
				if (elm.getInitialNodalForce(7) != dlg.eqFy2)
					changed = true;
				if (elm.getInitialNodalForce(8) != dlg.eqFz2)
					changed = true;
				if (elm.getInitialNodalForce(9) != dlg.eqMx2)
					changed = true;
				if (elm.getInitialNodalForce(10) != dlg.eqMy2)
					changed = true;
				if (elm.getInitialNodalForce(11) != dlg.eqMz2)
					changed = true;
				elm.setInitialNodalForce(0, dlg.eqFx1);
				elm.setInitialNodalForce(1, dlg.eqFy1);
				elm.setInitialNodalForce(2, dlg.eqFz1);
				elm.setInitialNodalForce(3, dlg.eqMx1);
				elm.setInitialNodalForce(4, dlg.eqMy1);
				elm.setInitialNodalForce(5, dlg.eqMz1);
				elm.setInitialNodalForce(6, dlg.eqFx2);
				elm.setInitialNodalForce(7, dlg.eqFy2);
				elm.setInitialNodalForce(8, dlg.eqFz2);
				elm.setInitialNodalForce(9, dlg.eqMx2);
				elm.setInitialNodalForce(10, dlg.eqMy2);
				elm.setInitialNodalForce(11, dlg.eqMz2);
				
				//Setting elmPreDisplacement
				if (elm.getElmPreDisplacement(0) != dlg.psDx1)
					changed = true;
				if (elm.getElmPreDisplacement(1) != dlg.psDy1)
					changed = true;
				if (elm.getElmPreDisplacement(2) != dlg.psDz1)
					changed = true;
				if (elm.getElmPreDisplacement(3) != dlg.psRx1)
					changed = true;
				if (elm.getElmPreDisplacement(4) != dlg.psRy1)
					changed = true;
				if (elm.getElmPreDisplacement(5) != dlg.psRz1)
					changed = true;
				if (elm.getElmPreDisplacement(6) != dlg.psDx2)
					changed = true;
				if (elm.getElmPreDisplacement(7) != dlg.psDy2)
					changed = true;
				if (elm.getElmPreDisplacement(8) != dlg.psDz2)
					changed = true;
				if (elm.getElmPreDisplacement(9) != dlg.psRx2)
					changed = true;
				if (elm.getElmPreDisplacement(10) != dlg.psRy2)
					changed = true;
				if (elm.getElmPreDisplacement(11) != dlg.psRz2)
					changed = true;
				elm.setElmPreDisplacement(0, dlg.psDx1);
				elm.setElmPreDisplacement(1, dlg.psDy1);
				elm.setElmPreDisplacement(2, dlg.psDz1);
				elm.setElmPreDisplacement(3, dlg.psRx1);
				elm.setElmPreDisplacement(4, dlg.psRy1);
				elm.setElmPreDisplacement(5, dlg.psRz1);
				elm.setElmPreDisplacement(6, dlg.psDx2);
				elm.setElmPreDisplacement(7, dlg.psDy2);
				elm.setElmPreDisplacement(8, dlg.psDz2);
				elm.setElmPreDisplacement(9, dlg.psRx2);
				elm.setElmPreDisplacement(10, dlg.psRy2);
				elm.setElmPreDisplacement(11, dlg.psRz2);
				
				//Setting LiberationsAtExtremities
				elm.setLiberation(0, dlg.Ldx1);
				elm.setLiberation(1, dlg.Ldy1);
				elm.setLiberation(2, dlg.Ldz1);
				elm.setLiberation(3, dlg.Lrx1);
				elm.setLiberation(4, dlg.Lry1);
				elm.setLiberation(5, dlg.Lrz1);
				elm.setLiberation(6, dlg.Ldx2);
				elm.setLiberation(7, dlg.Ldy2);
				elm.setLiberation(8, dlg.Ldz2);
				elm.setLiberation(9, dlg.Lrx2);
				elm.setLiberation(10, dlg.Lry2);
				elm.setLiberation(11, dlg.Lrz2);
			}
			
		}
		
		//parent.addToUndo((Command)this.clone());
		controller.unSelectAll();
		controller.compose();
		da.repaint();
		
		if (changed)
			parent.cleanResults();
		
	}
	
//*****************************************************************************
	
	/** Impossible to undo - not implemented. */
	public void undo() {
	}
	
//*****************************************************************************
	
	/** Impossible to redo - not implemented. */
	public void redo() {
	}
	
//*****************************************************************************
	
	/** Clone method. */
	public Object clone() {
		try {
			SetElmAttributesCommand cmd = (SetElmAttributesCommand)super.clone();
			return cmd;
		}catch (CloneNotSupportedException e) {
			throw new Error("Clonning ERROR - This should never happen!");
		}
	}
	
//*****************************************************************************
}

